import * as THREE from 'three';
import dat from 'dat.gui';
import { SceneUtils } from 'three/examples/jsm/utils/SceneUtils';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

export function init05(width, height) {
  // 创建一个场景，它将包含我们所有的元素，如对象，相机和灯光。
  const scene = new THREE.Scene();

  // 创建一个摄像机，它定义了我们正在查看的位置。
  const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);

  // 创建一个渲染器和设置大小
  const renderer = new THREE.WebGLRenderer();
  renderer.setClearColor(new THREE.Color(0x000000));
  renderer.setSize(width, height);
  renderer.shadowMap.enabled = true;

  // 创建平面
  const planeGeometry = new THREE.PlaneGeometry(60, 40, 1, 1);
  const planeMaterial = new THREE.MeshLambertMaterial({
    color: 0xffffff
  });
  const plane = new THREE.Mesh(planeGeometry, planeMaterial);

  // 旋转并定位平面
  plane.rotation.x = -0.5 * Math.PI;
  plane.position.x = 0;
  plane.position.y = 0;
  plane.position.z = 0;
  // 接收阴影
  plane.receiveShadow = true;
  // 将平面添加到场景中
  scene.add(plane);

  // 将相机定位并指向场景的中心
  camera.position.set(-30, 40, 30);
  camera.lookAt(scene.position);

  // 添加光源
  const ambientLight = new THREE.AmbientLight(0x3c3c3c);
  scene.add(ambientLight);

  // 为阴影添加聚光灯
  const spotLight = new THREE.SpotLight(0xffffff, 1.2, 150, 120);
  spotLight.position.set(-40, 60, -10);
  spotLight.castShadow = true;
  scene.add(spotLight);

  // 顶点
  const vertics = [
    new THREE.Vector3(1, 3, 1),
    new THREE.Vector3(1, 3, -1),
    new THREE.Vector3(1, -1, 1),
    new THREE.Vector3(1, -1, -1),
    new THREE.Vector3(-1, 3, -1),
    new THREE.Vector3(-1, 3, 1),
    new THREE.Vector3(-1, -1, -1),
    new THREE.Vector3(-1, -1, 1)
  ];

  // 面
  const faces = [
    new THREE.Face3(0, 2, 1),
    new THREE.Face3(2, 3, 1),
    new THREE.Face3(4, 6, 5),
    new THREE.Face3(6, 7, 5),
    new THREE.Face3(4, 5, 1),
    new THREE.Face3(5, 0, 1),
    new THREE.Face3(7, 6, 2),
    new THREE.Face3(6, 3, 2),
    new THREE.Face3(5, 7, 0),
    new THREE.Face3(7, 2, 0),
    new THREE.Face3(1, 3, 4),
    new THREE.Face3(3, 6, 4)
  ];

  const geometries = new THREE.Geometry();
  geometries.vertices = vertics;
  geometries.faces = faces;
  geometries.computeFaceNormals();

  const materials = [
    new THREE.MeshBasicMaterial({ color: 0x000000, wireframe: true }),
    new THREE.MeshLambertMaterial({
      opacity: 0.6,
      color: 0x44ff44,
      transparent: true
    })
  ];

  const mesh = new SceneUtils.createMultiMaterialObject(geometries, materials);
  scene.add(mesh);

  // 添加控制器
  function addControl(x, y, z) {
    const controls = new (function() {
      this.x = x;
      this.y = y;
      this.z = z;
    })();

    return controls;
  }

  // 所有控制变量
  const controlPoints = [];
  controlPoints.push(addControl(3, 5, 3));
  controlPoints.push(addControl(3, 5, 0));
  controlPoints.push(addControl(3, 0, 3));
  controlPoints.push(addControl(3, 0, 0));
  controlPoints.push(addControl(0, 5, 0));
  controlPoints.push(addControl(0, 5, 3));
  controlPoints.push(addControl(0, 0, 0));
  controlPoints.push(addControl(0, 0, 3));

  // 变量控制器
  const gui = new dat.GUI();
  const target = {
    clone() {
      const clonedGeometry = mesh.children[0].geometry.clone();
      const materials = [
        new THREE.MeshLambertMaterial({
          opacity: 0.6,
          color: 0xff44ff,
          transparent: true
        }),
        new THREE.MeshBasicMaterial({ color: 0x000000, wireframe: true })
      ];

      const mesh2 = new SceneUtils.createMultiMaterialObject(
        clonedGeometry,
        materials
      );
      mesh2.children.forEach(e => {
        e.castShadow = true;
      });

      mesh2.translateX(5);
      mesh2.translateZ(5);
      mesh2.name = 'clone';
      scene.remove(scene.getObjectByName('clone'));
      scene.add(mesh2);
    }
  };
  gui.add(target, 'clone');

  for (let i = 0; i < 8; i++) {
    const f1 = gui.addFolder('Vertices ' + (i + 1));
    f1.add(controlPoints[i], 'x', -10, 10);
    f1.add(controlPoints[i], 'y', -10, 10);
    f1.add(controlPoints[i], 'z', -10, 10);
  }

  // 视角操作
  const orbit = new OrbitControls(camera, renderer.domElement);

  // 将呈现器的输出添加到html元素中
  document.getElementById('webgl-output').appendChild(renderer.domElement);

  // 浏览器大小自适应
  window.addEventListener('resize', onResize, false);

  render();

  function render() {
    const vertices = [];
    for (let i = 0; i < 8; i++) {
      vertices.push(
        new THREE.Vector3(
          controlPoints[i].x,
          controlPoints[i].y,
          controlPoints[i].z
        )
      );
    }

    mesh.children.forEach(e => {
      e.geometry.vertices = vertices;
      e.geometry.verticesNeedUpdate = true;
      e.geometry.computeFaceNormals();
      delete e.geometry.__directGeometry;
    });

    orbit.update();
    renderer.render(scene, camera);
    requestAnimationFrame(render);
  }

  function onResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    renderer.setSize(width, height);
  }
}
